package com.wjk.kylin.rpc.core.netty.codec;

import com.wjk.kylin.rpc.core.netty.params.AbstractMessage;
import com.wjk.kylin.rpc.core.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;

import java.util.List;

/**
 * 必须和LengthFieldBasedFrameDecoder一起使用，避免粘包和半包
 * @author wjk
 */
@ChannelHandler.Sharable
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, AbstractMessage> {
    private final Serializer.Algorithm serializer;

    public MessageCodecSharable(Serializer.Algorithm serializer) {
        this.serializer = serializer;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, AbstractMessage message, List<Object> list) throws Exception {
        ByteBuf byteBuf = ctx.alloc().buffer();

        //1. 3 字节 魔数
        byteBuf.writeBytes(new byte[]{'w', 'j', 'k'});
        //2. 1 字节的指令类型
        byteBuf.writeByte(message.getMessageType());

        //6.获取数据
        byte[] bytes = serializer.serialize(message);

        int length = bytes.length;
        //7. 4字节长度
        byteBuf.writeInt(length);
        //8. 数据
        byteBuf.writeBytes(bytes);

        list.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
        //3 字节 魔数
        byteBuf.readByte();
        byteBuf.readByte();
        byteBuf.readByte();
        //字节的指令类型
        byte messageType = byteBuf.readByte();

        //内容长度
        int length = byteBuf.readInt();

        byte[] bytes = new byte[length];
        byteBuf.readBytes(bytes, 0, length);

        //序列化算法
        // 确定具体消息类型
        Class<? extends AbstractMessage> messageClass = AbstractMessage.getMessageClass(messageType);
        Object message = serializer.deserialize(bytes, messageClass);

        list.add(message);
    }
}
